/*
* =====================================================================================
*
*       Filename:  gdbus_client.c
*
*    Description:
*
*        Version:  1.0
*        Created:  02/17/2017 08:28:34 AM
*       Revision:  none
*       Compiler:  gcc
*
*         Author:  qiaotsh (), qiaotsh@neusoft.com
*   Organization:  www.neusoft.com
*
* =====================================================================================
*/
#include<stdio.h>
#include<gio/gio.h>
#include<glib.h>
#include<assert.h>
#include<fcntl.h>
#include<libusb.h>
#include <pthread.h>
#include<sys/time.h>

#include "common.h"
#include "ofprint_common.h"
#include "app_fp256_360.h"
#include "usb_device.h"
#include"ofprint-generated.h"
#include"ofprint-server.h"
#include "upgrade.h"

static int ENABLE_LOG_FILE = 0;	//通过配置文件使能logfile，0不输出日志到logfile，1输出日志

static GMainLoop *pLoop = NULL;
static Ofprint* pSkeleton=NULL;
static int logfileFD = 0;


char **finger_name;

OFP_ENROLL_STATUS_CALLBACK ofp_enroll_status_callback = NULL;
OFP_VERIFY_STATUS_CALLBACK ofp_verify_status_callback = NULL;
OFP_TOUCH_CALLBACK ofp_touch_callback = NULL;
OFP_IDENTIFY_WITH_MULTIPLE_USER_STATUS_CALLBACK ofp_identify_with_multiple_user_status_callback = NULL;


/********** 外部函数实现 **********/
char * ofp_new_string(char * old_str){
	char * str = NULL;

	if (old_str == NULL) {
		str = malloc(1);
		if (str != NULL)
			*str = '\0';
	} else {
		int l = strlen(old_str) + 1;
		str = malloc(l);
		if (str != NULL)
		{
			strncpy(str, old_str, l);
			//strncpy(str, old_str, sizeof(str));
			//str[l - 1] = '\0';
		}
	}

	return str;
}


int ofp_open_log_file(void)
{
	if(ENABLE_LOG_FILE)
	{
		if((logfileFD = open(OFP_LOG_FILE_NAME, O_RDWR|O_CREAT|O_APPEND, 0666))<0)
		{
			printf("%s open fail \n", OFP_LOG_FILE_NAME);
			logfileFD = 0;
			return -1;
		}
	}

	return 0;
}

int enable_printf_log(int flag)
{
	ENABLE_LOG_FILE = flag;
#if 0
	if(0 != ofp_open_log_file())
	{
		ENABLE_LOG_FILE = 0;
	}
#endif
	return 0;
}

//add by hcq, 20220331 12:00
int ofp_print_log(char *buf, int len)
{
#if 0
	if(ENABLE_LOG_FILE)
	{
		if(0 != ofp_open_log_file())
		{
			return -1;
		}

		if((NULL == buf) || (0 == len))
		{
			D_ERR("%s: the param is ERROR !!!\r\n", __func__);
			close(logfileFD);
			logfileFD = 0;
			return -1;
		}

		if((0 == logfileFD) || (-1 == logfileFD))
		{
			D_DBG("%s: the logfileFD not open, ERROR !!!\r\n", __func__);
			logfileFD = 0;
			return -1;
		}

		write(logfileFD, buf, len);
		close(logfileFD);
		logfileFD = 0;
	}
#endif
	return 0;
}


//add by hcq, 20220331 12:00
int ofp_print_log_time(char *buf, int len)
{
#if 0
	if(ENABLE_LOG_FILE)
	{
		if(0 != ofp_open_log_file())
		{
			return -1;
		}
		time_t current_time = time(NULL);//获取时间戳
		struct tm *local_time = localtime(&current_time);//将时间戳转换为本地时间
		char str[100] = {0};
		snprintf(str, 100, "%02d:%02d:%02d ", local_time->tm_hour, local_time->tm_min, local_time->tm_sec);

		if((NULL == buf) || (0 == len))
		{
			D_ERR("%s: the param is ERROR !!!\r\n", __func__);
			close(logfileFD);
			logfileFD = 0;
			return -1;
		}

		if((0 == logfileFD) || (-1 == logfileFD))
		{
			D_DBG("%s: the logfileFD not open, ERROR !!!\r\n", __func__);
			logfileFD = 0;
			return -1;
		}

		if(0 < strlen(str))
		{
			write(logfileFD, str, strlen(str));
		}

		write(logfileFD, buf, len);
		close(logfileFD);
		logfileFD = 0;
	}
#endif
	return 0;
}


int ofp_vprint_by_level(int print_level, FILE * __restrict stream,
						const char * __restrict format, va_list args)
{
	int ret = 0;
	int level_int = 0;

	switch (print_level)
	{
		case OFP_PRINT_LEVEL_EMERG:
			fprintf(stderr, "[EMERG] ");
			break;
		case OFP_PRINT_LEVEL_ALERT:
			fprintf(stderr, "[ALERT] ");
			break;
		case OFP_PRINT_LEVEL_CRIT:
			fprintf(stderr, "[ CRIT] ");
			break;
		case OFP_PRINT_LEVEL_ERROR:
			fprintf(stderr, "[ERROR] ");
			break;
		case OFP_PRINT_LEVEL_WARN:
			fprintf(stdout, "[ WARN] ");
			break;
		case OFP_PRINT_LEVEL_NOTICE:
			fprintf(stdout, "[ NOTE] ");
			break;
		case OFP_PRINT_LEVEL_INFO:
			fprintf(stdout, "[ INFO] ");
			break;
		case OFP_PRINT_LEVEL_DEBUG:
			fprintf(stdout, "[DEBUG] ");
			break;
		default:
			fprintf(stdout, "[UKNOW] ");
	}

	ret = vfprintf(stream, format, args);

	fflush(stream);

	return ret;
}

int ofp_print_info(const char * format, ...)
{
	int ret = 0;
	va_list args;

	va_start(args, format);
	ret = ofp_vprint_by_level(OFP_PRINT_LEVEL_INFO, stdout, format, args);
	va_end(args);

	return ret;
}

int ofp_ops_cancel(ofp_dev * dev)
{
	WD_DBG("start.\n");

	if (dev->enable == FALSE) {       // 设备不可用
		ofp_set_dev_status(dev, DEVS_COMM_DISABLE);
		return -1;
	}

	if(NULL == usb_get_dev_handle())
	{
		usb_dev_open(dev);
	}

	fp_cancel();
	//fp_read_invalid_pkg(3);//规避取消报文错位，add by hcq, 20230314

	usb_dev_close();

	WD_DBG("end.\n");

	return 0;
}

int ofp_set_mode(ofp_dev *dev)
{
	driver_info *priv = (driver_info *)dev->dev_priv;
	int mode_flag = priv->mode_flag;

	if((NULL == usb_get_dev_handle()) && (DRV_OK != usb_dev_open(dev)))
	{
		D_DBG("can't open device!!!\n");
		return -1;
	}

	D_DBG("mode_flag = %d\n", mode_flag);

	if(OFP_DEBUG_MODE_FLAG == mode_flag)
	{
		D_DBG("set OFP_DEBUG_MODE_FLAG.\n");
		fp_set_mode(FP_DEBUG_MODE_FLAG, strlen(FP_DEBUG_MODE_FLAG));
	}
	else if(OFP_USER_MODE_FLAG == mode_flag)
	{
		D_DBG("set OFP_USER_MODE_FLAG.\n");
		fp_set_mode(FP_USER_MODE_FLAG, strlen(FP_USER_MODE_FLAG));
	}

	usb_dev_close();

	D_DBG("end\n");

	return 0;
}


int ofp_set_reboot(ofp_dev *dev)
{
	driver_info *priv = (driver_info *)dev->dev_priv;
	int reboot_flag = priv->reboot_flag;

	D_DBG("start, reboot_flag = %d\n", reboot_flag);

	if(OFP_SET_REBOOT_FLAG != reboot_flag)
	{
		return 0;
	}

	if((NULL == usb_get_dev_handle()) && (DRV_OK != usb_dev_open(dev)))
	{
		D_DBG("can't open device!!!\n");
		return -1;
	}

	fp_reboot();

	usb_dev_close();

	return 0;
}


/*
 * 删除无效指纹（模组中存在，数据库中不存在）
*/
int ofp_delete_invalid_feature(ofp_dev *dev)
{
	WD_DBG("start.\n");

	if (dev->enable == FALSE) {
		WD_ERR("ofprint-serverd not enable!!!\n");
		return -1;
	}

	driver_info *priv = (driver_info *)dev->dev_priv;
	fprint_info *fprint_list = priv->fprint_list;
	uint8 index_table_info[INDEX_PAGE_NUM][32] = {{0}};

	if(0 != ofp_get_fprint_list(dev))
	{
		WD_ERR("ofp_get_fprint_list failed!!!\n");
		return -1;
	}

	// 读取特征列表
	for(int i = 0; i < OFP_FPRINT_NUM_MAX; i++)
	{
		if(true == fprint_list[i].enable)
		{
			uint16 fprint_id = fprint_list[i].fprint_id;

			if(FP_ENROLL_ID_MAX >= fprint_id)
			{
				index_table_info[fprint_id/256][(fprint_id%256)/8] |= (0x01 << (fprint_id%8));
			}
		}
	}

	WD_DBG("********========print index_table_info\n");
	for(int line = 0; line < INDEX_PAGE_NUM; line++)
	{
		for(int16 i = 0; i < 32; i++)
		{
			W_DBG("%02x ", index_table_info[line][i]);
		}
		W_DBG("\r\n");
	}
	fp_delete_invalid_template((uint8 *)index_table_info);

	return 0;
}

int ofp_upgrade_pt(ofp_dev *dev, int dev_exit_flag)
{
	int upgrade_ret = -1;
    int ret = 0;

    DBG("ofp_upgrade_pt =========================>enter\n");
	D_LOG("start.\n");

	//int cycle_time = 0;
	//while(1)
	for(int i = 0; i < 10; i++)//未识别到设备，循环超过10秒则退出
	{
		if(DRV_OK == usb_dev_open(dev))//规避模组不能一次复位成功问题，add by hcq, 20230425
		{
			fp_reboot();
			usb_dev_close();
			dev->dev_num = 0;
			usleep(1000 * 1000);
		}

		if(0 < dev->dev_num)
		{
			ret = -1;
            break;
		}

		//if(0 == upgrade_and_run())
		upgrade_ret = upgrade_and_run();
		if(0 == upgrade_ret)
		{
			D_LOG("upgrade_and_run success.\n");
			usleep(1000 * 1000);
			ret = 0;
            break;
		}
		else if(-2 == upgrade_ret)
		{
			ret = -2;
            break;
		}

		sleep(1);

		//cycle_time++;
		//if(10 < cycle_time)//未识别到设备，循环超过10秒则退出
		//{
		//	break;
		//}

	}
    DBG("ofp_upgrade_pt <=========================exit\n");

    return ret;
}


int ofp_upgrade_pt_notdelay(ofp_dev *dev, int dev_exit_flag)
{
	int upgrade_ret = -1;

	D_LOG("start.\n");


	//if(0 == upgrade_and_run())
	upgrade_ret = upgrade_and_run();
	if(0 == upgrade_ret)
	{
		D_LOG("upgrade_and_run success.\n");
		usleep(1000 * 1000);
		return 0;
	}
	else if(-2 == upgrade_ret)
	{
		return -2;
	}

	return DRV_ERR;
}


int32 ofp_check_firmware_version(ofp_dev *dev)
{
	driver_info *priv = (driver_info *)dev->dev_priv;
	int reboot_flag = priv->reboot_flag;
	int err = 0;
	pthread_t thr;

	D_DBG("start, check_firmware_version\n");

	if((NULL == usb_get_dev_handle()) && (DRV_OK != usb_dev_open(dev)))
	{
		D_DBG("can't open device!!!\n");
		return -1;
	}

	if((DRV_OK == fp_get_firmware_version()) && (0 < strlen(upgrade_new_firmware_version())))
	{
		//if(0 != strcmp(FIRMWARE_VERSION_NEW, fp_return_firmware_version()))
		if(((AUTO_UPGRADE == priv->config.upgrade_mode) && (0 != strcmp(FIRMWARE_VERSION_NEW, fp_return_firmware_version())))\
			|| ((SMART_UPGRADE == priv->config.upgrade_mode) && (FIRMWARE_VERSION_NUM_NEW > fp_return_firmware_version_num()))\
			|| (FORCE_UPGRADE == priv->config.upgrade_mode))
		{
			D_LOG("current firmware version is %s, new firmware version is %s.\n", \
				fp_return_firmware_version(), upgrade_new_firmware_version());
			//if(FIRMWARE_VERSION_NUM_NEW > fp_return_firmware_version_num())
			if(1)
			{
				if(0 == check_file_exit())
				{
					set_upgrade_state(1);
					fp_reboot();
					usb_dev_close();
					dev->dev_num = 0;
					//usb_dev_set_null();
					usleep(1000 * 1000);

#if 1
					ofp_upgrade_pt(dev, 1);
#else
					err = pthread_create(&thr, NULL, (void *)ofp_upgrade_pt, NULL);
					if(err != 0) {
						D_ERR(_("Can't create thread: %s\n"), strerror(err));
					}
#endif
				}
			}
			else
			{
				//rm_firmware_file();
				change_fw_upgrade_flag();
			}
		}
		else
		{
			D_DBG("firmware don't need upgrade.\n");
#if 0
			FILE *file;

			file = fopen(UPGRADE_FILE, "rb");
			if(NULL != file)
			{
				fclose(file);
				char system_cmd[200] = "rm ";
				//strncat(system_cmd, UPGRADE_FILE, sizeof(UPGRADE_FILE));
				strncat(system_cmd, UPGRADE_FILE, 100);
				D_DBG("%s\n", system_cmd);
				system(system_cmd);

				char rm_oms_conf_cmd[200] = "rm ";
    			strncat(rm_oms_conf_cmd, FW_VERSION_FILE, 100);
				D_DBG("%s\n", rm_oms_conf_cmd);
    			system(rm_oms_conf_cmd);
			}
#else
			change_fw_upgrade_flag();
#endif
		}
	}

	usb_dev_close();

	return 0;
}

//注册前判断当前指纹是否已录入 返回0表示已录入
int32 check_finger_is_enrolled()
{
	ofp_dev *dev = dev_ofprint;
	driver_info *priv = (driver_info *)dev->dev_priv;
	char msg_info[OFP_MSG_SIZE_MAX] = {0};
	uint16 identify_id = 0xffff;
	//uint16 identify_result_id = 0xffff;
	uint16 identify_result_id[ENROLL_NUM_MAX];
	int verifytimes = 0;
	int found_result = -1;//是否搜索到当前帐户指纹标志
	fprint_info *fprint_found = NULL;

	memset((char *)identify_result_id, 0xff, sizeof(identify_result_id));
	found_result = -1;
	if(DRV_OK == fp_auto_identify(3, identify_id, FP_CURRENT_OS_TYPE, identify_result_id, 0))
	{

			for(int n = 0; n < ENROLL_NUM_MAX; n++)
			{
				if(0xffff == identify_result_id[n])
				{
					WD_DBG("identify_result_id = %d\n", identify_result_id[n]);
					memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
					snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", OFP_VERIFY_REMOVE_AND_RETRY);
					//snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", OFP_VERIFY_SWIPE_TOO_SHORT);
					//ofp_verify_status_callback(NULL, OFP_VERIFY_STAGE_RETRY, msg_info);
#if 0
					ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STAGE_RETRY, msg_info);
#else
					//ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STATUS_NOMATCH, NULL);	//返回不匹配
#endif
					break;
				}

				ofp_find_fprint_info_byfprintid(dev, identify_result_id[n], &fprint_found);

				if(NULL != fprint_found)
				//if((NULL != fprint_found) && (0 == strcmp(priv->user_id, fprint_found->user_id)))//增加判断是否为当前帐户
				{
					memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
					WD_DBG("user_id = %s\n", fprint_found->user_id);
					//ofp_verify_status_callback(fprint_found->user_id, OFP_VERIFY_STATUS_MATCH, msg_info);
					found_result = 0;
				}
			}
	}

  return found_result;
}

static gboolean gdbus_handle_claim(Ofprint* skeleton,
									GDBusMethodInvocation *invocation,
									char *id, gboolean claimed)
{
	DEFAULT_DBG("\n");
	ofp_dev *dev = dev_ofprint;

    DBG("gdbus_handle_claim =======================> enter \n");


	if (dev->enable == FALSE) {
		WD_ERR("ofprint-serverd not enable!!!\n");
		//ofprint_set_state(pSkeleton, 0);
		ofprint_complete_claim(skeleton, invocation);
        DBG("gdbus_handle_claim <======================= error exit \n");
		return true;
	}

	driver_info *priv = (driver_info *)dev->dev_priv;

	if(NULL != id)
	{
		strcpy(priv->user_id, id);
	}

	int timeuse = 0;
	while(DEVS_COMM_IDLE != ofp_get_dev_status(dev))
	{
		usleep(10 * 1000);
		timeuse+=10;
		if(3000 < timeuse)
			break;
	}

	if(TRUE == claimed)
	{
		WD_DBG("claim the device start.\n");

		priv->dev_state |= DeviceStateClaimed;
		priv->set_dev_state(priv->dev_state);

		//ofp_set_dev_status (dev, DEVS_OPEN_DOING);                        //设备状态设置为：正在打开设备

		// 私有结构体控制变量成员设置为:CONTROL_FLAG_RUNNING
		//priv->ctrlFlag = CONTROL_FLAG_RUNNING;
		//fp_set_ctrlFlag(0);

		//fp_handshake();
		// 设置状态
		//ofp_set_dev_status (dev, DEVS_COMM_IDLE);                    //当前状态设置为：空闲状态
		//ofp_set_ops_abs_result (dev, OPS_OPEN_SUCCESS);              //操作结果设置为：打开设备成功
		//ofp_set_notify_abs_mid (dev, NOTIFY_OPEN_SUCCESS);           //提示消息设置为：打开设备成功
		WD_DBG("claim the device end.\n");
	}
	else
	{
		WD_DBG("release the device start.\n");
		priv->dev_state &=~ DeviceStateClaimed;
		priv->set_dev_state(priv->dev_state);

		//priv->ctrlFlag == CONTROL_FLAG_IDLE;
		//usb_dev_close();
		//ofp_set_dev_status (dev, DEVS_COMM_IDLE);                    //当前状态设置为：空闲状态
		//ofp_set_ops_abs_result (dev, OPS_CLOSE_SUCCESS);              //操作结果设置为：关闭设备成功
		//ofp_set_notify_abs_mid (dev, NOTIFY_CLOSE_SUCCESS);           //提示消息设置为：关闭设备成功
		WD_DBG("release the device end.\n");
	}
	DEFAULT_DBG("\n");
	ofprint_complete_claim(skeleton, invocation);
	DEFAULT_DBG("\n");
    DBG("gdbus_handle_claim <======================= exit \n");

	return TRUE;
}

void gdbus_enroll_pt(GSList * argv)
{
	Ofprint **p0;
	GDBusMethodInvocation **p1;
	char *p2;
	char *p3;

	p0 = g_slist_nth_data(argv,0);
	p1 = g_slist_nth_data(argv,1);
	p2 = g_slist_nth_data(argv,2);
	p3 = g_slist_nth_data(argv,3);

	Ofprint *skeleton = (Ofprint *)*p0;
	GDBusMethodInvocation *invocation = (GDBusMethodInvocation *)*p1;
	char *id = p2;
	char *finger = p3;
	ofp_dev *dev = dev_ofprint;
	driver_info *priv = (driver_info *)dev->dev_priv;
	uint16 enroll_id = 0xffff;
	int32 timeout_ms = priv->timeoutMS;
	char msg_info[OFP_MSG_SIZE_MAX] = {0};

    DBG("gdbus_enroll_pt ===================> enter \n");
	WD_LOG("start.\n");
	ofprint_complete_enroll(skeleton, invocation);
	//DEFAULT_DBG("\n");

#if 0 //测试数据已满提示
	snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 4); //数据满了，不能再录制更多指纹
	D_LOG("%s\n", msg_info);
	ofp_enroll_status_callback(id, OFP_ENROLL_STATUS_FAILED, msg_info);
	sleep(2);
	goto GDBUS_ENROLL_PT_END;
#endif

	if((dev->enable == FALSE) || (0 >= dev->dev_num))
	{
		DEFAULT_DBG("\n");
		ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_DISCONNECTED, "{}");
		DEFAULT_DBG("\n");
		goto GDBUS_ENROLL_PT_END;
	}

	if(DEVS_COMM_IDLE != ofp_get_dev_status(dev))//设备非空闲状态
	{
		//ofprint_complete_enroll(skeleton, invocation);
		memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
		snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}\n", 1); //未知错误
		DEFAULT_DBG("\n");
		ofp_enroll_status_callback(id, OFP_ENROLL_STATUS_FAILED, msg_info);
		DEFAULT_DBG("\n");
		goto GDBUS_ENROLL_PT_END;
	}

	if((NULL == usb_get_dev_handle()) && (DRV_OK != usb_dev_open(dev)))
	{
		DEFAULT_DBG("\n");
		ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_DISCONNECTED, "{}");//返回设备失联
		DEFAULT_DBG("\n");
		goto GDBUS_ENROLL_PT_END;
	}

	ofp_set_dev_status (dev, DEVS_ENROLL_DOING);                           //设备状态设置为：正在录入
	fp_read_invalid_pkg(5);//规避读取固件报文错位问题，add by hcq, 20230607 13:30

	if(0 != ofp_delete_invalid_feature(dev))
	{
		WD_ERR("ofp_delete_invalid_feature failed!!!\n");
	}

//增加判断指纹是否已录入
	while(1)
	{
		if(FP_CONTROL_FLAG_STOPPED == fp_get_ctrlFlag())//fp_set_ctrlFlag(FP_CONTROL_FLAG_STOPPED);
		{
			WD_DBG("user stoped!\n");
			break;
		}
		if(0 == check_finger_is_enrolled())
		{
			snprintf(priv->extra_info, EXTRA_INFO_LENGTH, \
					_("Enroll failed ! fingerprint already exist.\n"));// 用户提醒消息：指纹已录入
			WD_ERR("%s", priv->extra_info);
			//ofp_set_notify_abs_mid (dev, MID_EXTENDED_MESSAGE);
			//ofp_set_dev_status (dev, DEVS_COMM_IDLE);                  // 设备状态：空闲状态
			memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
			snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", OFP_ENROLL_FPRINT_ALREADY_EXIST);
			DEFAULT_DBG("\n");
			ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_RETRY, msg_info);
			//sleep(1);
			usleep(500 * 1000); //500ms
			DEFAULT_DBG("\n");
		}
		else
		{
			WD_DBG("check_finger_is_enrolled return !0 \n");
			snprintf (priv->extra_info, EXTRA_INFO_LENGTH, _("Enroll continue, please press your finger again.\n"));
			//ofp_set_notify_abs_mid (dev, MID_EXTENDED_MESSAGE);
			WD_DBG(priv->extra_info);
			memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
			snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 7);//拿开手指重新录入
			ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_RETRY, msg_info);
			break;
		}
	}

	enroll_id = fp_get_empty_enroll_id();
	if(FP_ENROLL_ID_MAX < enroll_id)
	{
		//ofprint_complete_enroll(skeleton, invocation);
		//此处待修改为设备存储已满, by hcq, 20230209
		//ofp_set_ops_abs_result (dev, OPS_ENROLL_FAIL);          // 设置操作结果：录入失败
		snprintf(priv->extra_info, EXTRA_INFO_LENGTH, \
				_("Enroll failed ! Storage space is full.\n"));// 用户提醒消息：指纹存储已满
		WD_ERR("%s", priv->extra_info);
		//ofp_set_notify_abs_mid (dev, MID_EXTENDED_MESSAGE);
		//ofp_set_dev_status (dev, DEVS_COMM_IDLE);                  // 设备状态：空闲状态
		memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
		snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 4); //数据满了，不能再录制更多指纹
		//snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 1); //未知错误
		//snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 2); //重复模板
		//snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 3); //录入中断
		DEFAULT_DBG("\n");
		ofp_enroll_status_callback(id, OFP_ENROLL_STATUS_FAILED, msg_info);
		//sleep(1);//测试休眠未提示录入已满，add by hcq, 20230324
		DEFAULT_DBG("\n");
		goto GDBUS_ENROLL_PT_END;
	}

	WD_DBG("enroll_id = %d\n", enroll_id);

	if(DRV_OK != fp_auto_enroll_start(enroll_id, 12, 0)) //20250218 6次修改为12次
	{
		//ofprint_complete_enroll(skeleton, invocation);
		switch(fp_get_ctrlFlag())
		{
			case FP_CONTROL_FLAG_ENROLLID_OUT_RANGE:
				WD_DBG(_("Enroll failed ! Storage space is full.\n"));// 用户提醒消息：指纹存储已满;
				memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
				snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 4); //数据满了，不能再录制更多指纹
				DEFAULT_DBG("\n");
				ofp_enroll_status_callback(id, OFP_ENROLL_STATUS_FAILED, msg_info);
				DEFAULT_DBG("\n");
				break;
			default:
				memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
				snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}\n", 1); //未知错误
				DEFAULT_DBG("\n");
				ofp_enroll_status_callback(id, OFP_ENROLL_STATUS_FAILED, msg_info);
				DEFAULT_DBG("\n");
				break;
		}
		fp_cancel();
		//fp_read_invalid_pkg(5);//规避取消报文错位，add by hcq, 20230314

		goto GDBUS_ENROLL_PT_END;
	}

	//ofprint_complete_enroll(skeleton, invocation);
	snprintf(priv->extra_info, EXTRA_INFO_LENGTH, _("enroll start ! Please press your finger.\n"));
	//ofp_set_notify_abs_mid (dev, MID_EXTENDED_MESSAGE);
	WD_DBG("%s", priv->extra_info);
	memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
	snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"progress\":%d}", 0);//录入进度
	DEFAULT_DBG("\n");
	ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_PASSED, msg_info);//开始录入
	DEFAULT_DBG("\n");

	WD_DBG("timeout_ms = %d\n", timeout_ms);

	while(1)
	{
		if(DRV_OK != fp_auto_enroll(timeout_ms))
		{
			switch(fp_get_ctrlFlag())
			{
				case FP_CONTROL_FLAG_STOPPED:
					memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
					snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 3); //录入中断
					ofp_enroll_status_callback(id, OFP_ENROLL_STATUS_FAILED, msg_info);
					break;
				case FP_CONTROL_FLAG_TIMEOUT:
					memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
					snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 3); //录入中断，是否有超时状态？
					ofp_enroll_status_callback(id, OFP_ENROLL_STATUS_FAILED, msg_info);
					//ofp_set_ops_abs_result (dev, OPS_ENROLL_TIMEOUT);          // 设置操作结果：录入超时
					//ofp_set_notify_abs_mid (dev, NOTIFY_ENROLL_TIMEOUT);
					break;
				case FP_CONTROL_FLAG_DEV_NOT_EXIST:
					ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_DISCONNECTED, "{}");//设备失联
					//ofp_set_ops_result (dev, OPS_COMM_ERROR);                              //操作结果设置为：通用操作错误
					//ofp_set_notify_abs_mid (dev, NOTIFY_COMM_DISABLE);                     //提示消息设置为：设备不可用
					break;
				default:
					memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
					snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}\n", 1); //未知错误
					ofp_enroll_status_callback(id, OFP_ENROLL_STATUS_FAILED, msg_info);
					//ofp_set_ops_abs_result (dev, OPS_ENROLL_ERROR);		   // 设置操作结果：录入错误
					//ofp_set_notify_abs_mid (dev, NOTIFY_ENROLL_ERROR);	   // 用户提醒消息：录入错误
					break;
			}
			fp_cancel();
			//fp_read_invalid_pkg(3);//规避取消报文错位，add by hcq, 20230314

			goto GDBUS_ENROLL_PT_END;
		}
		//DEFAULT_DBG("\n");

		if(0 != fp_get_enroll_finish_flag())
		{
			break;
		}

		uint8 enroll_time = fp_get_current_enroll_time();
		//DEFAULT_DBG("\n");
		if(0 < enroll_time)
		{
			uint8 create_feature_result = fp_get_enroll_create_feature_result(enroll_time);
			if(PROT_RESP_OK == create_feature_result)
			{
				switch(fp_get_enroll_result(enroll_time))
				{
					case  PROT_RESP_OK:	//录入成功
						snprintf (priv->extra_info, EXTRA_INFO_LENGTH, _("enroll times %d/12.\n"), enroll_time);//20250221
						//ofp_set_notify_abs_mid (dev, MID_EXTENDED_MESSAGE);
						WD_DBG("log_%s", priv->extra_info);
						memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
						snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"progress\":%d}", enroll_time * (100/dev->sample_times));//录入进度
						//WD_DBG("%s\n", msg_info);
						ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_PASSED, msg_info);
#if 0//验证图像异常提示
						memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
						//snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 3);//两次触摸的指纹信息重复率过高
						//snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 2);//图形不可用
						snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 1);//接触时间过短
						ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_RETRY, msg_info);
#endif
						break;
					default:
						snprintf (priv->extra_info, EXTRA_INFO_LENGTH, _("Enroll failed, please press your finger again.\n"));
						//ofp_set_notify_abs_mid (dev, MID_EXTENDED_MESSAGE);
						WD_DBG(priv->extra_info);
						memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
						snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 7);//拿开手指重新录入
						ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_RETRY, msg_info);
						break;
				}
			}
			else
			{
				switch(create_feature_result)
				{
					case PROT_RESP_OK:break;//生成特征成功
					case PROT_RESP_FPRINT_EXIST:	//指纹重复
						snprintf (priv->extra_info, EXTRA_INFO_LENGTH, _("Current fingerprint already exist, please press your finger again.\n"));
						//ofp_set_notify_abs_mid (dev, MID_EXTENDED_MESSAGE);
						WD_DBG(priv->extra_info);
						//bio_print_debug ("%s\n", bio_get_notify_mid_mesg(dev));
						DBG("Current fingerprint already exist, please press your finger again.\n");
						memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
						snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 4);//当前指纹已存在，请换其他手指
						ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_RETRY, msg_info);
						break;
					case PROT_RESP_POSITION_REPEATED:	//位置重复
						snprintf (priv->extra_info, EXTRA_INFO_LENGTH, _("Current fingerprint position repeated, please press your finger again.\n"));
						//ofp_set_notify_abs_mid (dev, MID_EXTENDED_MESSAGE);
						WD_DBG(priv->extra_info);
						//ofp_print_debug ("%s\n", bio_get_notify_mid_mesg(dev));
						DBG("Current position repeated, please press your finger again.\n");
						memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
						snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 3);//两次触摸的指纹信息重复率过高
						ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_RETRY, msg_info);
						break;
					case PROT_RESP_FPRINT_QUALITY_BAD:	//指纹质量不佳
						snprintf (priv->extra_info, EXTRA_INFO_LENGTH, _("The quality of current fingerprint is bad, please press your finger again.\n"));
						//ofp_set_notify_abs_mid (dev, MID_EXTENDED_MESSAGE);
						WD_DBG(priv->extra_info);
						//bio_print_debug ("%s\n", bio_get_notify_mid_mesg(dev));
						DBG("The quality of current fingerprint is bad, please press your finger again.\n");
						memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
						snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 2);//图形不可用
						ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_RETRY, msg_info);
						break;
					case PROT_RESP_FPRINT_AREA_TOO_SMALL:	//指纹面积过小
						snprintf (priv->extra_info, EXTRA_INFO_LENGTH, _("The area of current fingerprint is too small, please press your finger again.\n"));
						//ofp_set_notify_abs_mid (dev, MID_EXTENDED_MESSAGE);
						WD_DBG(priv->extra_info);
						//bio_print_debug ("%s\n", bio_get_notify_mid_mesg(dev));
						DBG("The area of current fingerprint is too small, please press your finger again.\n");
						memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
						snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 1);//接触时间过短
						ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_RETRY, msg_info);
						break;
					default:
						snprintf (priv->extra_info, EXTRA_INFO_LENGTH, _("Enroll failed, please press your finger again.\n"));
						//ofp_set_notify_abs_mid (dev, MID_EXTENDED_MESSAGE);
						WD_DBG(priv->extra_info);
						memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
						snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", 7);//拿开手指重新录入
						ofp_enroll_status_callback(id, OFP_ENROLL_STAGE_RETRY, msg_info);
						break;
				}

			}
		}
	}

	WD_DBG("enroll_id = %d\n", enroll_id);
	fp_cancel();//规避读取固件报文错位问题，add by hcq, 20230607 13:30

	fprint_info xfprint_info;
	xfprint_info.enable = true;
	strcpy(xfprint_info.user_id, id);
	strcpy(xfprint_info.fprint_name, finger);
	xfprint_info.fprint_id = enroll_id;
	ofp_add_fprint_info(dev, &xfprint_info);

	//ofprint_complete_enroll(skeleton, invocation);
	ofp_set_dev_status (dev, DEVS_COMM_IDLE);
	ofp_enroll_status_callback(id, OFP_ENROLL_STATUS_SUCCESS, "{}");

GDBUS_ENROLL_PT_END:
	fp_set_ctrlFlag(FP_CONTROL_FLAG_IDLE);
	if(CONTROL_FLAG_STOPING == priv->ctrlFlag)
	{
		priv->ctrlFlag = CONTROL_FLAG_STOPPED;
	}
	usb_dev_close();
	ofp_set_dev_status (dev, DEVS_COMM_IDLE);
	DEFAULT_DBG("\n");
	free(p0);
	free(p1);
	free(p2);
	free(p3);
	g_slist_free(argv);
    p0 = NULL;
    p1 = NULL;
    p2 = NULL;
    p3 = NULL;
    argv = NULL;
	WD_LOG("end.\n");

    DBG("gdbus_enroll_pt <=================== exit \n");

}

static gboolean gdbus_handle_enroll(Ofprint* skeleton,
											GDBusMethodInvocation *invocation,
											char *id, char *finger)
{
    DBG("gdbus_handle_enroll ===================>enter \n");
	WD_DBG("start, id=%s, finger=%s.\n", id, finger);

	int err = 0;
	pthread_t thr;

	GSList *argv = NULL;
	Ofprint **p0;
	GDBusMethodInvocation **p1;
	char *p2;
	char *p3;

	p0 = malloc(sizeof(void *));
	memcpy(p0, &skeleton, sizeof(void *));
	argv = g_slist_append(argv, p0);

	p1 = malloc(sizeof(void *));
	memcpy(p1, &invocation, sizeof(void *));
	argv = g_slist_append(argv, p1);

	p2 = ofp_new_string((char *)id);
	argv = g_slist_append(argv, p2);

	p3 = ofp_new_string((char *)finger);
	argv = g_slist_append(argv, p3);


	err = pthread_create(&thr, NULL, (void *)gdbus_enroll_pt, argv);

	if (err != 0) {
		WD_ERR(_("Can't create thread: %s\n"), strerror(err));
	}

	WD_DBG("end.\n");
    DBG("gdbus_handle_enroll <===================exit \n");

	return TRUE;
}

void gdbus_stop_enroll_pt(GSList * argv)
{
	Ofprint **p0;
	GDBusMethodInvocation **p1;

	p0 = g_slist_nth_data(argv,0);
	p1 = g_slist_nth_data(argv,1);

	Ofprint *skeleton = (Ofprint *)*p0;
	GDBusMethodInvocation *invocation = (GDBusMethodInvocation *)*p1;
	ofp_dev *dev = dev_ofprint;
	driver_info *priv = (driver_info *)dev->dev_priv;
	int timeout = 3 * 1000;
	int timeused = 0;

	WD_LOG("start.\n");

	if((dev->enable == FALSE) || (0 >= dev->dev_num))
	{
		goto GDBUS_STOP_ENROLL_PT_END;
	}

	if(ofp_get_dev_status(dev) == DEVS_COMM_IDLE)    // 如果设备为空闲状态
	{
		WD_DBG("DEVS_COMM_IDLE.\n");
		goto GDBUS_STOP_ENROLL_PT_END;
	}

	WD_DBG("continue.\n");

	// 设置状态位，用于通知用户中断
	priv->ctrlFlag = CONTROL_FLAG_STOPING;
	fp_set_ctrlFlag(FP_CONTROL_FLAG_STOPPED);

	while ((priv->ctrlFlag != CONTROL_FLAG_STOPPED) &&
		(priv->ctrlFlag != CONTROL_FLAG_DONE) &&
		(priv->ctrlFlag != CONTROL_FLAG_IDLE) &&
		(timeused < timeout))
	{
		timeused += 10;
		usleep(10 * 1000);
	}

GDBUS_STOP_ENROLL_PT_END:
	if ((priv->ctrlFlag == CONTROL_FLAG_STOPPED)
	    || (priv->ctrlFlag == CONTROL_FLAG_DONE))
	{
	    priv->ctrlFlag == CONTROL_FLAG_IDLE;
	}

	ofprint_complete_stop_enroll(skeleton, invocation);
	free(p0);
	free(p1);
	g_slist_free(argv);
	WD_LOG("end.\n");
}

static gboolean gdbus_handle_stop_enroll(Ofprint* skeleton,
											GDBusMethodInvocation *invocation)
{
    DBG("gdbus_handle_stop_enroll =====================>enter \n");
	WD_DBG("start.\n");

	int err = 0;
	pthread_t thr;

	GSList *argv = NULL;
	Ofprint **p0;
	GDBusMethodInvocation **p1;

	p0 = malloc(sizeof(void *));
	memcpy(p0, &skeleton, sizeof(void *));
	argv = g_slist_append(argv, p0);

	p1 = malloc(sizeof(void *));
	memcpy(p1, &invocation, sizeof(void *));
	argv = g_slist_append(argv, p1);

	err = pthread_create(&thr, NULL, (void *)gdbus_stop_enroll_pt, argv);

	if (err != 0) {
		WD_ERR(_("Can't create thread: %s\n"), strerror(err));
	}

	WD_DBG("end.\n");
    DBG("gdbus_handle_stop_enroll <=====================exit \n");

	//return FALSE;
	return TRUE;
}

/*
 * 初始化过程中先发起identify获取一键开机结果，并保存15秒钟
*/
int ofp_onekey_powerup_identify(ofp_dev *dev)
{
    DBG("ofp_onekey_powerup_identify ===================>enter\n");
	WD_DBG("start.\n");

	if((NULL == usb_get_dev_handle()) && (DRV_OK != usb_dev_open(dev)))
	{
		WD_DBG("can't open device!!!\n");

        DBG("ofp_onekey_powerup_identify ===================>error exit\n");
		return -1;
	}

	init_onekey_powerup_search_id();
	fp_onekey_powerup_identify(3, 0xffff, FP_CURRENT_OS_TYPE, get_onekey_powerup_search_id(), 20);
	fp_cancel();

	if(1 != get_onekey_powerup_flag())
	{
		set_onekey_powerup_flag(0);//若未读取到一键开机结果则设置为0
	}

	usb_dev_close();
    DBG("ofp_onekey_powerup_identify ===================> exit\n");

	return DRV_OK;
}


void gdbus_verify_pt(GSList * argv)
{
	Ofprint **p0;
	GDBusMethodInvocation **p1;
	char *p2;

	p0 = g_slist_nth_data(argv,0);
	p1 = g_slist_nth_data(argv,1);
	p2 = g_slist_nth_data(argv,2);

	Ofprint *skeleton = (Ofprint *)*p0;
	GDBusMethodInvocation *invocation = (GDBusMethodInvocation *)*p1;
	char *finger = p2;
	ofp_dev *dev = dev_ofprint;
	driver_info *priv = (driver_info *)dev->dev_priv;
	char msg_info[OFP_MSG_SIZE_MAX] = {0};
	uint16 identify_id = 0xffff;
	//uint16 identify_result_id = 0xffff;
	uint16 identify_result_id[ENROLL_NUM_MAX];
	int verifytimes = 0;
	int found_result = -1;//是否搜索到当前帐户指纹标志
	struct timeval tv_begin;
	struct timeval tv_end;
	int verify_time_ms = 0;
	fprint_info *fprint_found = NULL;

	WD_DBG("start, finger=%s.\n", finger);

	ofprint_complete_verify(skeleton, invocation);
	//DEFAULT_DBG("\n");
	if((dev->enable == FALSE) || ((0 >= dev->dev_num) && (0 == get_onekey_powerup_flag())))
	{
		//ofp_verify_status_callback("", OFP_VERIFY_STAGE_DISCONNECTED, "{}");//与设备失联
		//DEFAULT_DBG("\n");
		ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STAGE_DISCONNECTED, NULL);//与设备失联
		//DEFAULT_DBG("\n");
		goto GDBUS_VERIFY_PT_END;
	}

	if(DEVS_COMM_IDLE != ofp_get_dev_status(dev))//设备非空闲状态
	{
		memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
		snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}\n", 1); //未知错误
		//ofp_verify_status_callback("", OFP_VERIFY_STAGE_ERROR, msg_info);
		//DEFAULT_DBG("\n");
		ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STAGE_ERROR, msg_info);
		WD_DBG("ofp_get_dev_status(dev) = %d, not IDLE!\n", ofp_get_dev_status(dev));
		//DEFAULT_DBG("\n");
		goto GDBUS_VERIFY_PT_END;
	}

#if 0//识别过程中似乎会出现usb断开问题，故每次识别均重新打开usb
	if((NULL == usb_get_dev_handle()) && (DRV_OK != usb_dev_open(dev)))
	{
		//ofp_verify_status_callback("", OFP_VERIFY_STAGE_DISCONNECTED, "{}");//与设备失联
		//DEFAULT_DBG("\n");
		ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STAGE_DISCONNECTED, NULL);//与设备失联
		//DEFAULT_DBG("\n");
		WD_DBG("open device failed!\n");
		goto GDBUS_VERIFY_PT_END;
	}
#endif

	ofp_set_dev_status (dev, DEVS_VERIFY_DOING);         // 设备状态：正在验证
	gettimeofday(&tv_begin, NULL);

	memset((char *)identify_result_id, 0xff, sizeof(identify_result_id));
	//fp_read_invalid_pkg(5);//规避读取固件报文错位问题，add by hcq, 20230607 13:30，取消读空，避免睡眠时读不到一键开机结果
	//usleep(500 * 1000);//uos验证一键开机启动时验证通过，但未进入系统桌面，测试延时能进入

	//此处用于规避模组一键开机时，会将结果直接缓存在usb队列中，导致驱动初始化读取模组固件版本时，
	//先读到一键开机的结果，应答报文错位，流程混乱，后续应当由模组修改保证指令应答的准确性，add by hcq, 20230607
	if((1 == get_onekey_powerup_flag())&&(15*1000 > fp_get_increment_of_time_ms(get_onekey_powerup_tv_time())))
	{

		WD_LOG("received one key power up identify result.\n");
		//memcpy(identify_result_id, get_onekey_powerup_search_id(), get_onekey_powerup_search_num());
		for(int count = 0; count < get_onekey_powerup_search_num(); count++)
		{
			identify_result_id[count] = get_onekey_powerup_search_id()[count];
		}
		set_onekey_powerup_flag(0);
		//WD_DBG("sleep 700ms\n");
		//usleep(700 * 1000);
		if(1 == get_onekey_restart_flag())
		{
			set_onekey_restart_flag(0);
			//WD_DBG("sleep 1s\n");
			//sleep(1);
			int change_ms_value = get_restart_tv_begin_change_ms();
			//int delay_ms_value = 2000;//延时2000ms
			//int delay_ms_value = 1000;//延时1000ms
			int delay_ms_value = 0;//not delay
			if((0 < change_ms_value) && (change_ms_value < delay_ms_value))
			{
				usleep((delay_ms_value - change_ms_value) * 1000);
				WD_DBG("sleep %d ms\n", delay_ms_value - change_ms_value);
			}
			//usleep(200 * 1000);
			//WD_DBG("not delay.\n");
		}
		else
		{
			WD_DBG("sleep 2s\n");
			sleep(2);
		}
		goto GDBUS_VERIFY_PT_DEAL_WITH_RESULT_ID;//若为一键开机结果，则直接跳转到处理结果
	}
	set_onekey_powerup_flag(0);
	set_onekey_restart_flag(0);

#if 1//识别过程中似乎会出现usb断开问题，故每次识别均重新打开usb
		if((NULL == usb_get_dev_handle()) && (DRV_OK != usb_dev_open(dev)))
		{
			//ofp_verify_status_callback("", OFP_VERIFY_STAGE_DISCONNECTED, "{}");//与设备失联
			//DEFAULT_DBG("\n");
			ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STAGE_DISCONNECTED, NULL);//与设备失联
			//DEFAULT_DBG("\n");
			WD_DBG("open device failed!\n");
			goto GDBUS_VERIFY_PT_END;
		}
#endif


	//gettimeofday(&tv_begin, NULL);

#ifdef OFP_VERIFY_TIMES_MAX	//ofprint-server.h若定义了限制验证次数，则超过次数后无法进行指纹验证
	for(verifytimes = 0; verifytimes < OFP_VERIFY_TIMES_MAX; verifytimes++)
#else
	while(1)//是否需要限制验证次数
	//for(int i =0; i < 1; i++)
#endif
	{
		if(CONTROL_FLAG_STOPING == priv->ctrlFlag)
		{
			//ofp_verify_status_callback("", OFP_VERIFY_STATUS_NOMATCH, "{}");	//用户取消，返回不匹配
			//ofp_verify_status_callback(NULL, OFP_VERIFY_STATUS_NOMATCH, NULL);	//用户取消，返回不匹配
			//ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STATUS_NOMATCH, NULL);	//用户取消，返回不匹配
			WD_DBG("received CONTROL_FLAG_STOPING\n");
			goto GDBUS_VERIFY_PT_END;
		}
#if 0
		if((NULL == usb_get_dev_handle()) && (DRV_OK != usb_dev_open(dev)))//当识别到错误指纹时，usb会断开，此处规避，add by hcq, 20230323
		{
			//ofp_verify_status_callback("", OFP_VERIFY_STAGE_DISCONNECTED, "{}");//与设备失联
			DEFAULT_DBG("\n");
			ofp_verify_status_callback(NULL, OFP_VERIFY_STAGE_DISCONNECTED, NULL);//与设备失联
			DEFAULT_DBG("\n");
			if(CONTROL_FLAG_STOPING == priv->ctrlFlag)
			{
				//ofp_verify_status_callback("", OFP_VERIFY_STATUS_NOMATCH, "{}");	//用户取消，返回不匹配
				ofp_verify_status_callback(NULL, OFP_VERIFY_STATUS_NOMATCH, NULL);	//用户取消，返回不匹配
				goto GDBUS_VERIFY_PT_END;
			}
			continue;
			//goto GDBUS_VERIFY_PT_END;
		}
#endif
		//identify_result_id = 0xffff;
		memset((char *)identify_result_id, 0xff, sizeof(identify_result_id));
		found_result = -1;

		if(DRV_OK != fp_auto_identify(3, identify_id, FP_CURRENT_OS_TYPE, identify_result_id, 0))
		//if(DRV_OK != fp_auto_identify(3, identify_id, FP_ALL_OS_TYPE, &identify_result_id, 0))
		//if(DRV_OK != fp_auto_identify(3, identify_id, FP_WINDOWS_OS_TYPE, &identify_result_id, 0))
		//if(DRV_OK != fp_auto_identify(3, identify_id, FP_KYLIN_OS_TYPE, &identify_result_id, 0))
		//if(DRV_OK != fp_auto_identify(3, identify_id, FP_UOS_OS_TYPE, &identify_result_id, 0))
		{
			switch(fp_get_ctrlFlag())
			{
				case FP_CONTROL_FLAG_STOPPED:
					//ofp_set_ops_result (dev, OPS_COMM_STOP_BY_USER);
					//ofp_set_notify_mid (dev, NOTIFY_COMM_STOP_BY_USER);
					WD_DBG("FP_CONTROL_FLAG_STOPPED\n");
					break;
				case FP_CONTROL_FLAG_TIMEOUT:
					//fp_cancel();
					//ofp_set_ops_abs_result (dev, OPS_VERIFY_TIMEOUT);          // 设置操作结果：验证超时
					//ofp_set_notify_abs_mid (dev, NOTIFY_VERIFY_TIMEOUT);
					WD_DBG("FP_CONTROL_FLAG_TIMEOUT\n");
					break;
				case FP_CONTROL_FLAG_DEV_NOT_EXIST:
					//ofp_verify_status_callback("", OFP_VERIFY_STAGE_DISCONNECTED, "{}");//与设备失联
					ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STAGE_DISCONNECTED, NULL);//与设备失联
					WD_DBG("FP_CONTROL_FLAG_DEV_NOT_EXIST\n");
					//goto GDBUS_VERIFY_PT_END;//当识别到错误指纹时，usb会断开，此处规避，add by hcq, 20230323
					break;
				default:
					//fp_cancel();
					//ofp_set_ops_abs_result (dev, OPS_VERIFY_ERROR);		   // 设置操作结果：验证错误
					//ofp_set_notify_abs_mid (dev, NOTIFY_VERIFY_ERROR);	   // 用户提醒消息：验证错误
					WD_DBG("OPS_VERIFY_ERROR\n");
					break;
			}

			fp_cancel();
			//fp_read_invalid_pkg(3);//规避取消报文错位，add by hcq, 20230314
			fp_set_ctrlFlag(FP_CONTROL_FLAG_IDLE);
			if(CONTROL_FLAG_STOPING == priv->ctrlFlag)
			{
				//ofp_verify_status_callback("", OFP_VERIFY_STATUS_NOMATCH, "{}");	//用户取消，返回不匹配
				//ofp_verify_status_callback(NULL, OFP_VERIFY_STATUS_NOMATCH, NULL);	//用户取消，返回不匹配
				//ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STATUS_NOMATCH, NULL);	//用户取消，返回不匹配
				goto GDBUS_VERIFY_PT_END;
			}

			//memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
			//ofp_verify_status_callback(NULL, OFP_VERIFY_STATUS_NOMATCH, msg_info);
			//ofprint_complete_verify(skeleton, invocation);
			memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
			snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", OFP_VERIFY_REMOVE_AND_RETRY);
			ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STAGE_RETRY, msg_info);
			//ofp_verify_status_callback(NULL, OFP_VERIFY_STAGE_RETRY, msg_info);
			//usb_dev_close();//当识别到错误指纹时，usb会断开，此处规避，add by hcq, 20230323
			continue;
		}
#if 0
		if(0xffff == identify_result_id[0])
		{
			memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
			snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", OFP_VERIFY_REMOVE_AND_RETRY);
			//ofp_verify_status_callback("", OFP_VERIFY_STAGE_RETRY, msg_info);
			ofp_verify_status_callback(NULL, OFP_VERIFY_STAGE_RETRY, msg_info);
			//ofprint_complete_verify(skeleton, invocation);
			//ofp_set_dev_status (dev, DEVS_COMM_IDLE);
			//return TRUE;
			continue;
		}

		WD_DBG("identify_result_id[0] = %d\n", identify_result_id[0]);
#endif

GDBUS_VERIFY_PT_DEAL_WITH_RESULT_ID:


		for(int n = 0; n < ENROLL_NUM_MAX; n++)
		{
			if(0xffff == identify_result_id[n])
			{
				memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
				snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", OFP_VERIFY_REMOVE_AND_RETRY);
				//snprintf(msg_info, OFP_MSG_SIZE_MAX, "{\"subcode\":%d}", OFP_VERIFY_SWIPE_TOO_SHORT);
				//ofp_verify_status_callback(NULL, OFP_VERIFY_STAGE_RETRY, msg_info);
#if 0
				ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STAGE_RETRY, msg_info);
#else
				//ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STATUS_NOMATCH, NULL);	//返回不匹配
#endif
				break;
			}

			ofp_find_fprint_info_byfprintid(dev, identify_result_id[n], &fprint_found);

			//if(NULL != fprint_found)
			if((NULL != fprint_found) && (0 == strcmp(priv->user_id, fprint_found->user_id)))//增加判断是否为当前帐户
			{
				memset(msg_info, 0x00, OFP_MSG_SIZE_MAX);
				WD_DBG("user_id = %s\n", fprint_found->user_id);
				//ofp_verify_status_callback(fprint_found->user_id, OFP_VERIFY_STATUS_MATCH, msg_info);
				found_result = 0;
#if 0
				ofp_verify_status_callback(fprint_found->user_id, OFP_VERIFY_STATUS_MATCH, NULL);
#else //uos验证一键开机启动时验证通过，但未进入系统桌面，测试多发送几次是否能进入
				gettimeofday(&tv_end, NULL);

				if(tv_end.tv_usec > tv_begin.tv_usec)
				{
					verify_time_ms = (tv_end.tv_sec - tv_begin.tv_sec)*1000 +\
						(tv_end.tv_usec - tv_begin.tv_usec)/1000;
				}
				else
				{
					verify_time_ms = (tv_end.tv_sec - tv_begin.tv_sec - 1)*1000 +\
						(tv_end.tv_usec + 1000*1000 - tv_begin.tv_usec)/1000;
				}

				D_DBG("verify_time_ms = %d\n", verify_time_ms);

				if(80 > verify_time_ms)//测试50ms内完成一键开机指纹搜索结果读取，增加到80ms降低风险
				{
					//usleep(700 * 1000);//休眠700ms
					//sleep(2);//休眠2秒
					usleep(200 * 1000);//休眠200ms
				}

				if(CONTROL_FLAG_STOPING == priv->ctrlFlag)
				{
					fp_onekey_restart_identify_2(identify_result_id);
					goto GDBUS_VERIFY_PT_END;
				}
				ofp_verify_status_callback(fprint_found->user_id, OFP_VERIFY_STATUS_MATCH, NULL);
#endif
				goto GDBUS_VERIFY_PT_END;
				//usleep(10 * 1000);
				//break;//由uos生物识别代理调用stop verify结束
			}
#if 0
			else
			{
				WD_DBG("user_id = NULL\n");
				ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STATUS_NOMATCH, NULL);	//返回不匹配
			}
#endif
			//usleep(10 * 1000);

			if(FP_CONTROL_FLAG_STOPPED == fp_get_ctrlFlag())
			{
				WD_DBG("received CONTROL_FLAG_STOPING\n");
				if(NULL != usb_get_dev_handle())
				{
					fp_cancel();
				}
				//fp_read_invalid_pkg(3);//规避取消报文错位，add by hcq, 20230314
				goto GDBUS_VERIFY_PT_END;
			}
		}

		if(0 != found_result)
		{
			WD_DBG("user_id = NULL\n");
			if(CONTROL_FLAG_STOPING == priv->ctrlFlag)
			{
				fp_onekey_restart_identify_2(identify_result_id);
				goto GDBUS_VERIFY_PT_END;
			}
			ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STATUS_NOMATCH, NULL); //返回不匹配
			//goto GDBUS_VERIFY_PT_END;
		}

		usleep(200 * 1000);//休眠100ms，若收到取消指令则返回
		//usb_dev_close();//当识别到错误指纹时，usb会断开，此处规避，add by hcq, 20230323
	}
	DEFAULT_DBG("\n");
	if(NULL != usb_get_dev_handle())
	{
		fp_cancel();
	}

#ifdef OFP_VERIFY_TIMES_MAX
	if(OFP_VERIFY_TIMES_MAX == verifytimes)
	{
		//ofp_verify_status_callback("", OFP_VERIFY_STATUS_NOMATCH, "{}");
		DEFAULT_DBG("\n");
		ofp_verify_status_callback(priv->user_id, OFP_VERIFY_STATUS_NOMATCH, NULL);
		DEFAULT_DBG("\n");
	}
#endif

GDBUS_VERIFY_PT_END:
	//ofprint_complete_verify(skeleton, invocation);//此处会导致验证流程无法结束
	fp_set_ctrlFlag(FP_CONTROL_FLAG_IDLE);
	if(CONTROL_FLAG_STOPING == priv->ctrlFlag)
	{
		priv->ctrlFlag = CONTROL_FLAG_STOPPED;
	}
	usb_dev_close();
	//DEFAULT_DBG("\n");
	ofp_set_dev_status (dev, DEVS_COMM_IDLE);
	free(p0);
	free(p1);
	free(p2);
	g_slist_free(argv);
	//DEFAULT_DBG("\n");
	WD_LOG("end.\n");
}




static gboolean gdbus_handle_verify(Ofprint* skeleton,
											GDBusMethodInvocation *invocation,
											char *finger)
{
    DBG("gdbus_handle_verify ==========================>enter \n");
	WD_DBG("start, finger=%s.\n", finger);

	int err = 0;
	pthread_t thr;

	GSList *argv = NULL;
	Ofprint **p0;
	GDBusMethodInvocation **p1;
	char *p2;

	p0 = malloc(sizeof(void *));
	memcpy(p0, &skeleton, sizeof(void *));
	argv = g_slist_append(argv, p0);

	p1 = malloc(sizeof(void *));
	memcpy(p1, &invocation, sizeof(void *));
	argv = g_slist_append(argv, p1);

	p2 = ofp_new_string((char *)finger);
	argv = g_slist_append(argv, p2);

	err = pthread_create(&thr, NULL, (void *)gdbus_verify_pt, argv);

	if (err != 0) {
		WD_ERR(_("Can't create thread: %s\n"), strerror(err));
	}
	DEFAULT_DBG("\n");
    DBG("gdbus_handle_verify <==========================exit \n");

	return TRUE;
}

void gdbus_stop_verify_pt(GSList * argv)
{
	DEFAULT_DBG("\n");
	Ofprint **p0;
	GDBusMethodInvocation **p1;

	p0 = g_slist_nth_data(argv,0);
	p1 = g_slist_nth_data(argv,1);

	Ofprint *skeleton = (Ofprint *)*p0;
	GDBusMethodInvocation *invocation = (GDBusMethodInvocation *)*p1;
	ofp_dev *dev = dev_ofprint;
	driver_info *priv = (driver_info *)dev->dev_priv;
	int timeout = 3 * 1000;//3s 超时
	int timeused = 0;

    DBG("gdbus_stop_verify_pt ==========================>enter\n");
	WD_LOG("start.\n");

	if((dev->enable == FALSE) || (0 >= dev->dev_num))
	{
		goto GDBUS_STOP_VERIFY_PT_END;
	}

	if(ofp_get_dev_status(dev) == DEVS_COMM_IDLE)    // 如果设备为空闲状态
	{
		WD_DBG("DEVS_COMM_IDLE.\n");
		goto GDBUS_STOP_VERIFY_PT_END;
	}

	WD_DBG("continue.\n");

	// 设置状态位，用于通知用户中断
	priv->ctrlFlag = CONTROL_FLAG_STOPING;
	fp_set_ctrlFlag(FP_CONTROL_FLAG_STOPPED);

	while ((priv->ctrlFlag != CONTROL_FLAG_STOPPED) &&
		(priv->ctrlFlag != CONTROL_FLAG_DONE) &&
		(priv->ctrlFlag != CONTROL_FLAG_IDLE) &&
		(timeused < timeout) &&
		(ofp_get_dev_status(dev) != DEVS_COMM_IDLE))
	{
		timeused += 10;//EM1600DEV_FINGER_CHECK_INTERVAL_MS;
		usleep(10 * 1000);//usleep(EM1600DEV_FINGER_CHECK_INTERVAL_MS * 1000);
	}

GDBUS_STOP_VERIFY_PT_END:
	if ((priv->ctrlFlag == CONTROL_FLAG_STOPPED)
	    || (priv->ctrlFlag == CONTROL_FLAG_DONE)
	    || (ofp_get_dev_status(dev) == DEVS_COMM_IDLE))
	{
		priv->ctrlFlag == CONTROL_FLAG_IDLE;
	}

	ofprint_complete_stop_verify(skeleton, invocation);
	free(p0);
	free(p1);
	g_slist_free(argv);
	WD_LOG("end.\n");
    DBG("gdbus_stop_verify_pt <==========================exit\n");

}

static gboolean gdbus_handle_stop_verify(Ofprint* skeleton,
											GDBusMethodInvocation *invocation)
{
    DBG("gdbus_handle_stop_verify ======================>enter\n");
	WD_DBG("start.\r\n");

	int err = 0;
	pthread_t thr;

	GSList *argv = NULL;
	Ofprint **p0;
	GDBusMethodInvocation **p1;

	p0 = malloc(sizeof(void *));
	memcpy(p0, &skeleton, sizeof(void *));
	argv = g_slist_append(argv, p0);

	p1 = malloc(sizeof(void *));
	memcpy(p1, &invocation, sizeof(void *));
	argv = g_slist_append(argv, p1);

	err = pthread_create(&thr, NULL, (void *)gdbus_stop_verify_pt, argv);

	if (err != 0) {
		WD_ERR(_("Can't create thread: %s\n"), strerror(err));
	}
	DEFAULT_DBG("\n");
    DBG("gdbus_handle_stop_verify <======================exit\n");

	return TRUE;
}

static gboolean gdbus_handle_delete_finger(Ofprint* skeleton,
											GDBusMethodInvocation *invocation,
											char *id, char *finger)
{
    DBG("gdbus_handle_delete_finger =====================>enter \n");
	WD_DBG("start, id=%s, finger=%s.\n", id, finger);

	ofp_dev *dev = dev_ofprint;
	fprint_info *fprint_found = NULL;
	uint16 enroll_id = 0xffff;
	int ret = 0;
	int index = 0;

	if((dev->enable == FALSE) || (0 >= dev->dev_num))// 设备不可用
	{
		WD_LOG("device disable!!!\n");
		goto GDBUS_HANDLE_DELETE_FINGER_END;
	}

	if(DEVS_COMM_IDLE != ofp_get_dev_status(dev))//设备非空闲状态
	{
		WD_LOG("device not idle!!!\n");
		goto GDBUS_HANDLE_DELETE_FINGER_END;
	}

	if((NULL == usb_get_dev_handle()) && (DRV_OK != usb_dev_open(dev)))
	{
		WD_LOG("open device failed!!!\n");
		goto GDBUS_HANDLE_DELETE_FINGER_END;
	}

	ofp_set_dev_status (dev, DEVS_CLEAN_DOING);       //设备状态设置为：正在清理特征数据
	DEFAULT_DBG("\n");
	index = ofp_find_fprint_info(dev, id, finger, &fprint_found);
	if(NULL == fprint_found)
	{
		WD_LOG("not find id=%s finger=%s!!!\n", id, finger);
		goto GDBUS_HANDLE_DELETE_FINGER_END;
	}

	enroll_id = fprint_found->fprint_id;
	WD_DBG("enroll_id = %d\n", enroll_id);
	ret = fp_delete_template(enroll_id, 1);
	DEFAULT_DBG("\n");
	if (ret == 0)
	{
		ofp_del_fprint_info(dev, id, finger);
	}
	else
	{
		WD_LOG("fp_delete_template enroll_id=%d failed!!!\n", enroll_id);
	}
	DEFAULT_DBG("\n");

#if 0
	if(0 != ofp_delete_invalid_feature(dev))
	{
		WD_ERR("ofp_delete_invalid_feature failed!!!\n");
	}
#endif

GDBUS_HANDLE_DELETE_FINGER_END:
	DEFAULT_DBG("\n");
	usb_dev_close();
	ofp_set_dev_status (dev, DEVS_COMM_IDLE);
	DEFAULT_DBG("\n");
	ofprint_complete_delete_finger(skeleton, invocation);
	WD_DBG("end.\n");
    DBG("gdbus_handle_delete_finger <=====================exit \n");

	return TRUE;
}

static gboolean gdbus_handle_delete_all_fingers(Ofprint* skeleton,
											GDBusMethodInvocation *invocation,
											char *id)
{
    DBG("gdbus_handle_delete_all_fingers ======================>enter \n");
	WD_DBG("start, id=%s.\n", id);

	ofp_dev *dev = dev_ofprint;
	driver_info *priv = (driver_info *)dev->dev_priv;
	fprint_info *fprint_list = priv->fprint_list;

	if((dev->enable == FALSE) || (0 >= dev->dev_num))// 设备不可用
	{
		WD_LOG("device disable!!!\n");
		goto GDBUS_HANDLE_DELETE_ALL_FINGERS_END;
	}

	if(DEVS_COMM_IDLE != ofp_get_dev_status(dev))//设备非空闲状态
	{
		WD_LOG("device not idle!!!\n");
		goto GDBUS_HANDLE_DELETE_ALL_FINGERS_END;
	}

	if((NULL == usb_get_dev_handle()) && (DRV_OK != usb_dev_open(dev)))
	{
		WD_LOG("open device failed!!!\n");
		goto GDBUS_HANDLE_DELETE_ALL_FINGERS_END;
	}

	ofp_set_dev_status (dev, DEVS_CLEAN_DOING);       //设备状态设置为：正在清理特征数据

	for(int i = 0; i < OFP_FPRINT_NUM_MAX; i++)
	{
		if((true == fprint_list[i].enable)\
			&&(0 == strcmp(id, fprint_list[i].user_id)))
		{
			uint16 enroll_id = fprint_list[i].fprint_id;
			int ret = 0;
			ret = fp_delete_template(enroll_id, 1);
			if(DRV_OK != ret)
			{
				WD_ERR("fp_delete_template enroll_id %d failed!!!\n", enroll_id);
			}
			else
			{
				ofp_del_fprint_info(dev, fprint_list[i].user_id, fprint_list[i].fprint_name);
			}
		}
	}
	DEFAULT_DBG("\n");

#if 0
	if(0 != ofp_delete_invalid_feature(dev))
	{
		WD_ERR("ofp_delete_invalid_feature failed!!!\n");
	}
#endif

GDBUS_HANDLE_DELETE_ALL_FINGERS_END:
	DEFAULT_DBG("\n");
	usb_dev_close();
	ofp_set_dev_status (dev, DEVS_COMM_IDLE);
	DEFAULT_DBG("\n");
	ofprint_complete_delete_all_fingers(skeleton, invocation);
	WD_DBG("end.\n");
    DBG("gdbus_handle_delete_all_fingers <======================exit \n");

	return TRUE;
}

static gboolean gdbus_handle_list_fingers(Ofprint* skeleton,
											GDBusMethodInvocation *invocation,
											char *id)
{
    DBG("gdbus_handle_list_fingers =======================>enter \n");
	WD_DBG("start, id=%s.\n", id);

	ofp_dev *dev = dev_ofprint;
	driver_info *priv = (driver_info *)dev->dev_priv;
	fprint_info *fprint_list = priv->fprint_list;
	int i = 0;
	int count = 0;

	finger_name = (char **)g_new0(char*, OFP_FPRINT_NUM_MAX);//二维数组

	if(0 >= dev->dev_num)
	{
		set_onekey_powerup_flag(0);
		set_onekey_restart_flag(0);
		WD_LOG("can't open device.\n");
		ofprint_complete_list_fingers(skeleton, invocation, (const gchar *const *)finger_name);
		return true;
	}

	if(0 != ofp_get_fprint_list(dev))
	{
		DEFAULT_DBG("\n");
		ofprint_complete_list_fingers(skeleton, invocation, (const gchar *const *)finger_name);
		DEFAULT_DBG("\n");
		return true;
	}

	for(i = 0; i < OFP_FPRINT_NUM_MAX; i++)
	{
		if((true == fprint_list[i].enable)\
			&& (0 == strcmp(id, fprint_list[i].user_id)))
		{
			char *tmp = (char *)g_new0(char, OFP_FPRINT_NAME_LEN_MAX);
			strncpy(tmp, fprint_list[i].fprint_name, OFP_FPRINT_NAME_LEN_MAX);
			finger_name[count++] = tmp;
			WD_DBG("%s\n", finger_name[count-1]);
		}
	}
	DEFAULT_DBG("\n");
	ofprint_complete_list_fingers(skeleton, invocation, (const gchar *const *)finger_name);
	DEFAULT_DBG("\n");

	for(i = 0; i < count; i++)
	{
		DEFAULT_DBG("\n");
		g_free(finger_name[i]);
	}
	DEFAULT_DBG("\n");
	g_free(finger_name);
	finger_name = NULL;

	WD_DBG("end.\n");
    DBG("gdbus_handle_list_fingers <=======================exit \n");


	return TRUE;
}

static gboolean gdbus_handle_rename_finger(Ofprint* skeleton,
											GDBusMethodInvocation *invocation,
											char *id, char *finger, char *newName)
{
    DBG("gdbus_handle_rename_finger =====================>enter \n");
	WD_DBG("start, id=%s, finger=%s, newName=%s.\n", id, finger, newName);

	ofp_dev *dev = dev_ofprint;
	fprint_info *fprint_found = NULL;
	int index = 0;

	//ofp_set_dev_status (dev, DEVS_RENAME_DOING);       //设备状态设置为：正在清理特征数
	index = ofp_find_fprint_info(dev, id, finger, &fprint_found);
	DEFAULT_DBG("\n");
	if(NULL == fprint_found)
	{
		WD_ERR("ofp_find_fprint_info not found!!!\n");
	}
	else
	{
		if(0 < strlen(newName))
		{
			strcpy(fprint_found->fprint_name, newName);
			if(0 != ofp_set_fprint_info(dev, index, fprint_found))
			{
				WD_ERR("ofp_set_fprint_info failed!!!\n");
			}
		}
	}
	DEFAULT_DBG("\n");
	ofprint_complete_rename_finger(skeleton, invocation);
	WD_DBG("end.\n");
    DBG("gdbus_handle_rename_finger <=====================exit \n");

	return TRUE;
}

void gdbus_identify_with_multiple_user_pt(GSList * argv)
{
	Ofprint **p0;
	GDBusMethodInvocation **p1;

	p0 = g_slist_nth_data(argv,0);
	p1 = g_slist_nth_data(argv,1);

	Ofprint *skeleton = (Ofprint *)*p0;
	GDBusMethodInvocation *invocation = (GDBusMethodInvocation *)*p1;

	ofp_dev *dev = dev_ofprint;
	driver_info *priv = (driver_info *)dev->dev_priv;
	char msg_info[OFP_MSG_SIZE_MAX] = {0};
	uint16 identify_id = 0xffff;
	uint16 identify_result_id[ENROLL_NUM_MAX];
	int verifytimes = 0;
	int found_result = -1;//是否搜索到当前帐户指纹标志
	struct timeval tv_begin;
	struct timeval tv_end;
	int verify_time_ms = 0;
	fprint_info *fprint_found = NULL;

	WD_DBG("start.\n");

	ofprint_complete_identify_with_multiple_user(skeleton, invocation);
	DEFAULT_DBG("\n");
	if((dev->enable == FALSE) || (0 >= dev->dev_num))
	{
		DEFAULT_DBG("\n");
		ofp_identify_with_multiple_user_status_callback(NULL);//与设备失联
		DEFAULT_DBG("\n");
		goto GDBUS_IDENTIFY_WITH_MULTIPLE_USER_PT_END;
	}

	if(DEVS_COMM_IDLE != ofp_get_dev_status(dev))//设备非空闲状态
	{
		DEFAULT_DBG("\n");
		ofp_identify_with_multiple_user_status_callback(NULL);
		DEFAULT_DBG("\n");
		goto GDBUS_IDENTIFY_WITH_MULTIPLE_USER_PT_END;
	}

#if 1//识别过程中似乎会出现usb断开问题，故每次识别均重新打开usb
	if((NULL == usb_get_dev_handle()) && (DRV_OK != usb_dev_open(dev)))
	{
		DEFAULT_DBG("\n");
		ofp_identify_with_multiple_user_status_callback(NULL);//与设备失联
		DEFAULT_DBG("\n");
		goto GDBUS_IDENTIFY_WITH_MULTIPLE_USER_PT_END;
	}
#endif

	ofp_set_dev_status (dev, DEVS_VERIFY_DOING);         // 设备状态：正在验证
	memset((char *)identify_result_id, 0xff, sizeof(identify_result_id));
	//fp_read_invalid_pkg(5);//规避读取固件报文错位问题，add by hcq, 20230607 13:30 取消读空，避免睡眠时一键开机读取不到结果
	//usleep(500 * 1000);//uos验证一键开机启动时验证通过，但未进入系统桌面，测试延时能进入

	//此处用于规避模组一键开机时，会将结果直接缓存在usb队列中，导致驱动初始化读取模组固件版本时，
	//先读到一键开机的结果，应答报文错位，流程混乱，后续应当由模组修改保证指令应答的准确性，add by hcq, 20230607
	if((1 == get_onekey_powerup_flag())&&(15*1000 > fp_get_increment_of_time_ms(get_onekey_powerup_tv_time())))
	{

		WD_LOG("received one key power up identify result.\n");
		//memcpy(identify_result_id, get_onekey_powerup_search_id(), get_onekey_powerup_search_num());
		for(int count = 0; count < get_onekey_powerup_search_num(); count++)
		{
			identify_result_id[count] = get_onekey_powerup_search_id()[count];
		}
		set_onekey_powerup_flag(0);
		WD_DBG("sleep 700ms\n");
		usleep(700 * 1000);
		goto GDBUS_IDENTIFY_WITH_MULTIPLE_USER_PT_DEAL_WITH_RESULT_ID;//若为一键开机结果，则直接跳转到处理结果
	}
	set_onekey_powerup_flag(0);

	gettimeofday(&tv_begin, NULL);

	found_result = -1;

	if(DRV_OK != fp_auto_identify(3, identify_id, FP_CURRENT_OS_TYPE, identify_result_id, 1000))
	{
		switch(fp_get_ctrlFlag())
		{
			case FP_CONTROL_FLAG_STOPPED:
				WD_DBG("FP_CONTROL_FLAG_STOPPED\n");
				break;
			case FP_CONTROL_FLAG_TIMEOUT:
				WD_DBG("FP_CONTROL_FLAG_TIMEOUT\n");
				break;
			case FP_CONTROL_FLAG_DEV_NOT_EXIST://与设备失联
				WD_DBG("FP_CONTROL_FLAG_DEV_NOT_EXIST\n");
				break;
			default:
				WD_DBG("OPS_VERIFY_ERROR\n");
				break;
		}

		fp_cancel();
		//fp_read_invalid_pkg(3);//规避取消报文错位，add by hcq, 20230314
		fp_set_ctrlFlag(FP_CONTROL_FLAG_IDLE);
		ofp_identify_with_multiple_user_status_callback(NULL);
		goto GDBUS_IDENTIFY_WITH_MULTIPLE_USER_PT_END;
	}
	fp_cancel();

GDBUS_IDENTIFY_WITH_MULTIPLE_USER_PT_DEAL_WITH_RESULT_ID:


	for(int n = 0; n < ENROLL_NUM_MAX; n++)
	{
		if(0xffff == identify_result_id[n])
		{
			ofp_identify_with_multiple_user_status_callback(NULL);
			break;
		}

		ofp_find_fprint_info_byfprintid(dev, identify_result_id[n], &fprint_found);


		if(NULL != fprint_found)
		{
			found_result = 0;
#if 1
			ofp_identify_with_multiple_user_status_callback(fprint_found->user_id);
#else //uos验证一键开机启动时验证通过，但未进入系统桌面，测试多发送几次是否能进入
			gettimeofday(&tv_end, NULL);

			if(tv_end.tv_usec > tv_begin.tv_usec)
			{
				verify_time_ms = (tv_end.tv_sec - tv_begin.tv_sec)*1000 +\
					(tv_end.tv_usec - tv_begin.tv_usec)/1000;
			}
			else
			{
				verify_time_ms = (tv_end.tv_sec - tv_begin.tv_sec - 1)*1000 +\
					(tv_end.tv_usec + 1000*1000 - tv_begin.tv_usec)/1000;
			}

			D_DBG("verify_time_ms = %d\n", verify_time_ms);

			if(80 > verify_time_ms)//测试50ms内完成一键开机指纹搜索结果读取，增加到80ms降低风险
			{
				usleep(600 * 1000);//休眠600ms
			}
			ofp_identify_with_multiple_user_status_callback(fprint_found->user_id);
#endif
			goto GDBUS_IDENTIFY_WITH_MULTIPLE_USER_PT_END;
		}
	}

	if(0 != found_result)
	{
		WD_DBG("user_id = NULL\n");
		ofp_identify_with_multiple_user_status_callback(NULL); //返回不匹配
	}

GDBUS_IDENTIFY_WITH_MULTIPLE_USER_PT_END:
	fp_set_ctrlFlag(FP_CONTROL_FLAG_IDLE);
	if(CONTROL_FLAG_STOPING == priv->ctrlFlag)
	{
		priv->ctrlFlag = CONTROL_FLAG_STOPPED;
	}
	usb_dev_close();
	DEFAULT_DBG("\n");
	ofp_set_dev_status (dev, DEVS_COMM_IDLE);
	free(p0);
	free(p1);
	g_slist_free(argv);
	DEFAULT_DBG("\n");
}




static gboolean gdbus_handle_identify_with_multiple_user(Ofprint* skeleton,
											GDBusMethodInvocation *invocation)
{
    DBG("gdbus_handle_identify_with_multiple_user ============================>enter\n");
	WD_DBG("start.\n");

	int err = 0;
	pthread_t thr;

	GSList *argv = NULL;
	Ofprint **p0;
	GDBusMethodInvocation **p1;

	p0 = malloc(sizeof(void *));
	memcpy(p0, &skeleton, sizeof(void *));
	argv = g_slist_append(argv, p0);

	p1 = malloc(sizeof(void *));
	memcpy(p1, &invocation, sizeof(void *));
	argv = g_slist_append(argv, p1);

	err = pthread_create(&thr, NULL, (void *)gdbus_identify_with_multiple_user_pt, argv);

	if (err != 0) {
		WD_ERR(_("Can't create thread: %s\n"), strerror(err));
	}
	DEFAULT_DBG("\n");
    DBG("gdbus_handle_identify_with_multiple_user <============================exit\n");

	return TRUE;
}

void gdbus_stop_identify_with_multiple_user_pt(GSList * argv)
{
    DBG("gdbus_stop_identify_with_multiple_user_pt ==========================>enter \n");
	WD_DBG("start.\r\n");

	Ofprint **p0;
	GDBusMethodInvocation **p1;

	p0 = g_slist_nth_data(argv,0);
	p1 = g_slist_nth_data(argv,1);

	Ofprint *skeleton = (Ofprint *)*p0;
	GDBusMethodInvocation *invocation = (GDBusMethodInvocation *)*p1;
	ofp_dev *dev = dev_ofprint;
	driver_info *priv = (driver_info *)dev->dev_priv;
	int timeout = 3 * 1000;
	int timeused = 0;

	if((dev->enable == FALSE) || (0 >= dev->dev_num))
	{
		goto GDBUS_STOP_IDENTIFY_WITH_MULTIPLE_USER_PT_END;
	}

	if(ofp_get_dev_status(dev) == DEVS_COMM_IDLE)	 // 如果设备为空闲状态
	{
		WD_DBG("DEVS_COMM_IDLE.\n");
		goto GDBUS_STOP_IDENTIFY_WITH_MULTIPLE_USER_PT_END;
	}

	WD_DBG("start.\n");

	// 设置状态位，用于通知用户中断
	priv->ctrlFlag = CONTROL_FLAG_STOPING;
	fp_set_ctrlFlag(FP_CONTROL_FLAG_STOPPED);

	while ((priv->ctrlFlag != CONTROL_FLAG_STOPPED) &&
		(priv->ctrlFlag != CONTROL_FLAG_DONE) &&
		(priv->ctrlFlag != CONTROL_FLAG_IDLE) &&
		(timeused < timeout) &&
		(ofp_get_dev_status(dev) != DEVS_COMM_IDLE))
	{
		timeused += 10;//EM1600DEV_FINGER_CHECK_INTERVAL_MS;
		usleep(10 * 1000);//usleep(EM1600DEV_FINGER_CHECK_INTERVAL_MS * 1000);
	}

GDBUS_STOP_IDENTIFY_WITH_MULTIPLE_USER_PT_END:
	if ((priv->ctrlFlag == CONTROL_FLAG_STOPPED)
		|| (priv->ctrlFlag == CONTROL_FLAG_DONE)
		|| (ofp_get_dev_status(dev) == DEVS_COMM_IDLE))
	{
		priv->ctrlFlag == CONTROL_FLAG_IDLE;
	}
	DEFAULT_DBG("\n");
	ofprint_complete_stop_verify(skeleton, invocation);
	free(p0);
	free(p1);
	g_slist_free(argv);
	DEFAULT_DBG("\n");
    DBG("gdbus_stop_identify_with_multiple_user_pt <==========================exit \n");

}


static gboolean gdbus_handle_stop_identify_with_multiple_user(Ofprint* skeleton,
											GDBusMethodInvocation *invocation)
{
    DBG("gdbus_handle_stop_identify_with_multiple_user ===========================>enter\n");
	WD_DBG("start.\r\n");

	int err = 0;
	pthread_t thr;

	GSList *argv = NULL;
	Ofprint **p0;
	GDBusMethodInvocation **p1;

	p0 = malloc(sizeof(void *));
	memcpy(p0, &skeleton, sizeof(void *));
	argv = g_slist_append(argv, p0);

	p1 = malloc(sizeof(void *));
	memcpy(p1, &invocation, sizeof(void *));
	argv = g_slist_append(argv, p1);

	err = pthread_create(&thr, NULL, (void *)gdbus_stop_identify_with_multiple_user_pt, argv);

	if (err != 0) {
		WD_ERR(_("Can't create thread: %s\n"), strerror(err));
	}
	DEFAULT_DBG("\n");
    DBG("gdbus_handle_stop_identify_with_multiple_user <===========================exit\n");

	return TRUE;

}




static void gdbus_signal_enroll_status(char *id, int code, char *msg)
{
	WD_DBG("start.\r\n");
	ofprint_emit_enroll_status(pSkeleton, id, code, msg);
	//WD_DBG("end.\r\n");
}

static void gdbus_signal_verify_status(char *id, int code, char *msg)
{
	WD_DBG("start.\r\n");
	ofprint_emit_verify_status(pSkeleton, id, code, msg);
	//WD_DBG("end.\r\n");
}

static void gdbus_signal_touch(char *id, gboolean pressed)
{
	WD_DBG("start.\r\n");
	ofprint_emit_touch(pSkeleton, id, pressed);
	WD_DBG("end.\r\n");
}

static void gdbus_identify_with_multiple_user_status(char *uuid)
{
	WD_DBG("start.\r\n");
	ofprint_emit_identify_with_multiple_user_status(pSkeleton, uuid);
	WD_DBG("end.\r\n");
}


int ofp_set_dev_state(uint8 state)
{
	//ofprint_set_state(pSkeleton, state);
	return 0;
}


void GBusAcquired_Callback (GDBusConnection *connection,
	const gchar *name,
	gpointer user_data)
{
	ofp_dev *dev = dev_ofprint;
	driver_info *priv = (driver_info *)dev->dev_priv;
	GError *error = NULL;


	WD_DBG("GBusAcquired_Callback has been invoked\n");
	//printf("GBusAcquired_Callback the name = %s\n",name);
	//printf("GBusAcquired_Callback the user_data = %s\n",(char*)user_data);

	pSkeleton =  ofprint_skeleton_new ();
	g_signal_connect(pSkeleton,"handle-claim",G_CALLBACK(gdbus_handle_claim),NULL);
	g_signal_connect(pSkeleton,"handle-enroll",G_CALLBACK(gdbus_handle_enroll),NULL);
	g_signal_connect(pSkeleton,"handle-stop-enroll",G_CALLBACK(gdbus_handle_stop_enroll),NULL);
	g_signal_connect(pSkeleton,"handle-verify",G_CALLBACK(gdbus_handle_verify),NULL);
	g_signal_connect(pSkeleton,"handle-stop-verify",G_CALLBACK(gdbus_handle_stop_verify),NULL);
	g_signal_connect(pSkeleton,"handle-delete-finger",G_CALLBACK(gdbus_handle_delete_finger),NULL);
	g_signal_connect(pSkeleton,"handle-delete-all-fingers",G_CALLBACK(gdbus_handle_delete_all_fingers),NULL);
	g_signal_connect(pSkeleton,"handle-list-fingers",G_CALLBACK(gdbus_handle_list_fingers),NULL);
	g_signal_connect(pSkeleton,"handle-rename-finger",G_CALLBACK(gdbus_handle_rename_finger),NULL);
	g_signal_connect(pSkeleton,"handle-identify-with-multiple-user",G_CALLBACK(gdbus_handle_identify_with_multiple_user),NULL);
	g_signal_connect(pSkeleton,"handle-stop-identify-with-multiple-user",G_CALLBACK(gdbus_handle_stop_identify_with_multiple_user),NULL);

	ofp_enroll_status_callback = gdbus_signal_enroll_status;
	ofp_verify_status_callback = gdbus_signal_verify_status;
	ofp_touch_callback = gdbus_signal_touch;
	ofp_identify_with_multiple_user_status_callback = gdbus_identify_with_multiple_user_status;

	ofprint_set_name(pSkeleton, dev->device_name);
	if(1 == get_upgrade_state())
	{
		WD_LOG("device state = 0x%02x\n", DeviceStateNormal);
		ofprint_set_state(pSkeleton, DeviceStateNormal);
	}
	else
	{
		WD_LOG("device state = 0x%02x\n", priv->dev_state);
		ofprint_set_state(pSkeleton, priv->dev_state);
	}
	ofprint_set_type_(pSkeleton, DeviceTypeTouch);
	ofprint_set_capability(pSkeleton, DeviceCapAutologin);

	(void) g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(pSkeleton),
											connection,
											OMS_GDBUS_OFP_OBJECT_PATH,
											&error);

	if(error != NULL){
		g_print("Error: Failed to export object. Reason: %s.\n", error->message);
		g_error_free(error);
		g_main_loop_quit(pLoop);
	}
}

void GBusNameAcquired_Callback (GDBusConnection *connection,
	const gchar *name,
	gpointer user_data)
{
	printf(_("name_acquired_cb called, Acquired bus name: %s\n"), OMS_GDBUS_OFP_BUS_NAME);
}

void GBusNameLost_Callback (GDBusConnection *connection,
	const gchar *name,
	gpointer user_data)
{
	WD_DBG(_("GBusNameLost_Callback has been invoked******\n"));
	//g_main_loop_quit(pLoop);
}

void ofprint_upgrade_pt(void)
{
    DBG("ofprint_upgrade_pt =========================>enter\n");
	ofp_dev * dev = dev_ofprint;

	if((NULL == dev)||(NULL == dev->ops_discover))
	{
		return;
	}

	if(0 < dev->ops_discover(dev))
	{
		ofp_check_firmware_version(dev);//检查版本升级固件放在初始化DBS后执行, by hcq, 20231102
	}

    DBG("ofprint_upgrade_pt <=========================exit\n");
}

int main(int argc,char* argv[])
{
	ofp_dev * dev = NULL;
	int ret = 0;
	pthread_t thr_upgrade;
	int err = 0;

	if(0 != ofp_conf_init())
	{
		WD_ERR("ofp_conf_init failed!!!\n");
		return -1;
	}

	ofp_dev_init();
	dev = dev_ofprint;
	driver_info *priv = (driver_info *)dev->dev_priv;

	WD_DBG("driver start.\n");

	if(0 != upgrade_module_init())
	{
		D_ERR("upgrade_module_init failed!!!\n");
	}

	read_fw_version();//读取待升级固件版本

	//ofp_open_log_file();


	ret = usb_lib_init(dev);
	if(0 > ret)
	{
		WD_DBG("libusb_init failed.\n");
		return -1;
	}

	usb_dev_get_port_path();

	ofp_drv_init(dev);
	if(0 < dev->ops_discover(dev))
	{
		priv->dev_state |= DeviceStateNormal;
		ofp_onekey_powerup_identify(dev);
		//ofp_check_firmware_version(dev);
		ofp_set_mode(dev);
		ofp_set_reboot(dev);
		WD_DBG("DeviceStateNormal=====================\n");
	}
	else
	{
		priv->dev_state &= ~DeviceStateNormal;
		WD_LOG("not discover the device.\n");
		ofp_upgrade_pt_notdelay(dev, 0);
	}

	if(0 == usb_dev_get_port_path_valid_flag())
	{
		usb_dev_get_port_path();
	}

	if(0 == usb_dev_enable_autosuspend())
	{
		D_LOG("usb_dev_enable_autosuspend.\r\n");
	}

	//ofp_ops_cancel(dev);//运行发送cancel，避免模组处于录入或验证等状态而导致异常
	ofp_get_fprint_list(dev);

	err = pthread_create(&thr_upgrade, NULL, (void *)ofprint_upgrade_pt, NULL);

	if (err != 0) {
		WD_ERR("Can't create thread: %s\n", strerror(err));
	}

	usleep(100 * 1000);

#if 1
	if(1 == get_upgrade_state())
	{
		WD_LOG("upgrading!\n");
		sleep(2);
	}
#endif

	pLoop = g_main_loop_new(NULL, FALSE);

	guint own_id =
	g_bus_own_name (OMS_GDBUS_OFP_BUS_TYPE,
		OMS_GDBUS_OFP_BUS_NAME,
		G_BUS_NAME_OWNER_FLAGS_NONE,//G_BUS_NAME_OWNER_FLAGS_REPLACE|G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT,//
		GBusAcquired_Callback,
		GBusNameAcquired_Callback,
		GBusNameLost_Callback,
		NULL,
		NULL);

#if 0
	if(0 < dev->ops_discover(dev))
	{
		ofp_check_firmware_version(dev);//检查版本升级固件放在初始化DBS后执行, by hcq, 20231102
	}
#endif
	/* * emit my signal1 every 1 second to trigger example communication */
	//g_timeout_add(3000, (GSourceFunc)Emit_Test_Status, NULL);

	g_main_loop_run(pLoop);
	g_main_loop_unref(pLoop);

	g_bus_unown_name(own_id);

    libusb_hotplug_deregister_callback(dev_ofprint->ctx, (dev_ofprint->usb_info.callback_handle)[1]);

    libusb_hotplug_deregister_callback(dev_ofprint->ctx, (dev_ofprint->usb_info.callback_handle)[0]);

	usb_lib_exit(dev_ofprint);
	//ofp_conf_free();
	ofp_dev_free(dev_ofprint);

	return 0;
}

